package ui.component;

import com.sun.prism.impl.Disposer;
import java.util.LinkedList;
import java.util.List;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.ToggleGroup;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.control.cell.ComboBoxTableCell;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.util.Callback;
import model.Attribute;
import model.Table;

/**
 *
 * @author Merli András-Bertalan
 */
public class AttributeView extends VBox {

    private Table currentTable;
    private ObservableList<Attribute> attributes;
    private ObservableList<Table> tables;
    private final ToggleGroup isPrimaryToggleGroup = new ToggleGroup();

    public void setAttributes(final ObservableList<Attribute> attributes) {
        this.attributes = attributes;
    }

    public final void updateUi(final Table currentTable, final List<Table> tables) {
        this.attributes = FXCollections.observableArrayList(currentTable.getAttributes());
        this.tables = FXCollections.observableArrayList(tables);
        this.currentTable = currentTable;

        getChildren().clear();

        // Table attribute table
        final TableView table = new TableView();

        table.setEditable(
                true);
        final Label label = new Label("Edit Table Attributes");

        label.setFont(
                new Font("Arial", 20));

        TableColumn nameColumn = new TableColumn("Name");
        TableColumn typeColumn = new TableColumn("Type");
        TableColumn deleteRowColumn = new TableColumn<>("Delete");
        //

        nameColumn.setMinWidth(
                100);
        typeColumn.setMinWidth(
                100);
        //
        nameColumn.setCellValueFactory(
                new PropertyValueFactory<Attribute, String>("name"));
        nameColumn.setCellFactory(TextFieldTableCell.forTableColumn());
        nameColumn.setOnEditCommit(
                new EventHandler<TableColumn.CellEditEvent<Attribute, String>>() {
                    @Override
                    public void handle(TableColumn.CellEditEvent<Attribute, String> t) {
                        ((Attribute) t.getTableView().getItems().get(
                                t.getTablePosition().getRow())).setName(t.getNewValue());
                    }
                });
        typeColumn.setCellValueFactory(
                new PropertyValueFactory<Attribute, String>("type"));
        typeColumn.setCellFactory(TextFieldTableCell.forTableColumn());
        typeColumn.setOnEditCommit(
                new EventHandler<TableColumn.CellEditEvent<Attribute, String>>() {
                    @Override
                    public void handle(TableColumn.CellEditEvent<Attribute, String> t) {
                        ((Attribute) t.getTableView().getItems().get(
                                t.getTablePosition().getRow())).setType(t.getNewValue());
                    }
                });

        TableColumn isUniqueColumn = new TableColumn<>("Unique?");
        isUniqueColumn.setMinWidth(
                50);
        isUniqueColumn.setCellValueFactory(
                new PropertyValueFactory<Attribute, Boolean>("isUnique"));
        isUniqueColumn.setCellFactory(CheckBoxTableCell.forTableColumn(isUniqueColumn));
//        isUniqueColumn.setCellFactory(new Callback<TableColumn<Attribute, Boolean>, TableCell<Attribute, Boolean>>() {
//            public TableCell<Attribute, Boolean> call(TableColumn<Attribute, Boolean> p) {
//
//                return new CheckBoxTableCell<Attribute, Boolean>();
//
//            }
//        });
        isUniqueColumn.setOnEditCommit(
                new EventHandler<TableColumn.CellEditEvent<Attribute, Boolean>>() {
                    @Override
                    public void handle(TableColumn.CellEditEvent<Attribute, Boolean> t) {
                        t.getRowValue().setIsUnique(t.getNewValue());
                    }
                });
        //Delete row Button
        deleteRowColumn.setCellValueFactory(
                new Callback<TableColumn.CellDataFeatures<Disposer.Record, Boolean>, ObservableValue<Boolean>>() {
                    @Override
                    public ObservableValue<Boolean> call(TableColumn.CellDataFeatures<Disposer.Record, Boolean> p) {
                        return new SimpleBooleanProperty(p.getValue() != null);
                    }
                });
        //Adding the Button to the cell
        deleteRowColumn.setCellFactory(
                new Callback<TableColumn<Disposer.Record, Boolean>, TableCell<Disposer.Record, Boolean>>() {
                    @Override
                    public TableCell<Disposer.Record, Boolean> call(TableColumn<Disposer.Record, Boolean> p) {
                        return new ButtonCell();
                    }
                });

        // IsPrimary? column
        TableColumn isPrimaryColumn = new TableColumn("Primary?");
        isPrimaryColumn.setMinWidth(
                50);
        isPrimaryColumn.setCellValueFactory(new PropertyValueFactory<Attribute, Boolean>("isPrimary"));
        //Adding the RadioButton to the cell
        isPrimaryColumn.setCellFactory(
                new Callback<TableColumn<Disposer.Record, Boolean>, TableCell<Disposer.Record, Boolean>>() {
                    @Override
                    public TableCell<Disposer.Record, Boolean> call(TableColumn<Disposer.Record, Boolean> p) {
                        return new RadioButtonCell();
                    }
                });
        isPrimaryColumn.setOnEditCommit(
                new EventHandler<TableColumn.CellEditEvent<Attribute, Boolean>>() {
                    @Override
                    public void handle(TableColumn.CellEditEvent<Attribute, Boolean> t) {
                        t.getRowValue().setIsPrimary(t.getNewValue());
                    }
                });

        // reference column
        List<String> tableNamesStrings = new LinkedList<>();
        tableNamesStrings.add("");
        for (Table t : tables) {
            tableNamesStrings.add(t.getName());
        }
        ObservableList<String> tableNames = FXCollections.observableArrayList(tableNamesStrings);
        tableNames.remove(currentTable.getName());
        TableColumn referenceColumn = new TableColumn("Reference");
        referenceColumn.setEditable(true);
        referenceColumn.setMinWidth(150);
        referenceColumn.setCellValueFactory(
                new PropertyValueFactory<Attribute, String>("referenceTableName"));
        referenceColumn.setCellFactory(ComboBoxTableCell.forTableColumn(tableNames));
        referenceColumn.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<Attribute, String>>() {
            @Override
            public void handle(TableColumn.CellEditEvent<Attribute, String> t) {
                System.out.println("edit commited");
                Attribute currentAttribute = t.getRowValue();
                currentAttribute.setReferenceTableName(t.getNewValue());
                System.out.println("Reference Table: " + currentAttribute.getReferenceTableName());
                Table referenceTable = null;
                for (Table t2 : tables) {
                    if (t2.getName().equals(currentAttribute.getReferenceTableName())) {
                        referenceTable = t2;
                    }
                }
                if (referenceTable != null) {
                    for (Attribute a : referenceTable.getAttributes()) {
                        System.out.println(currentAttribute.getType() + " - " + a.getType());
                        if (a.getType().equals(currentAttribute.getType())) {
                            currentAttribute.setReferenceTableName(referenceTable.getName());
                            currentAttribute.setReferenceAttributeName(a.getName());
                            currentAttribute.setReferenceTable(referenceTable);
                            currentAttribute.setReferenceAttribute(a);

                            a.setReferenceTableName(currentTable.getName());
                            a.setReferenceAttributeName(currentAttribute.getName());
//                            a.setReferenceTable(currentTable);
//                            a.setReferenceAttribute(currentAttribute);
                        }
                    }
                }
            }
        });

        ////////////
        table.getColumns()
                .addAll(nameColumn, typeColumn, isUniqueColumn, isPrimaryColumn, referenceColumn, deleteRowColumn);

        table.setItems(attributes);

        final TextField nameTextField = new TextField();

        nameTextField.setPromptText(
                "Name");
        nameTextField.setMaxWidth(nameColumn.getPrefWidth());
        final TextField typeTextField = new TextField();

        typeTextField.setMaxWidth(typeColumn.getPrefWidth());
        typeTextField.setPromptText(
                "Type");
        final CheckBox isUniqueCheckBox = new CheckBox("Unique?");

        isUniqueCheckBox.setMaxWidth(isUniqueColumn.getPrefWidth());

        final Button addAttributeButton = new Button("Add");

        addAttributeButton.setOnAction(
                new EventHandler<ActionEvent>() {
                    @Override
                    public void handle(ActionEvent e) {
                        attributes.add(new Attribute(nameTextField.getText(), typeTextField.getText(), isUniqueCheckBox.isSelected(), false));
                        nameTextField.clear();
                        typeTextField.clear();
                        isUniqueCheckBox.setSelected(false);
                    }
                });

        HBox addAttributeBox = new HBox();

        addAttributeBox.getChildren()
                .addAll(nameTextField, typeTextField, isUniqueCheckBox, addAttributeButton);
        addAttributeBox.setSpacing(
                3);

        setSpacing(
                5);
        setPadding(
                new Insets(10, 0, 0, 10));
        getChildren()
                .addAll(label, table, addAttributeBox);
    }

    public void saveCurrentState() {
        currentTable.setAttributes(attributes);
    }

    private class ButtonCell extends TableCell<Disposer.Record, Boolean> {

        final Button cellButton = new Button("Delete");

        ButtonCell() {

            //Action when the button is pressed
            cellButton.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent t) {
                    // get Selected Item
                    Attribute currentItem = (Attribute) ButtonCell.this.getTableView().getItems().get(ButtonCell.this.getIndex());
                    //remove selected item from the table list
                    attributes.remove(currentItem);
                }
            });
        }

        //Display button if the row is not empty
        @Override
        protected void updateItem(Boolean t, boolean empty) {
            super.updateItem(t, empty);
            if (!empty) {
                setGraphic(cellButton);
            }
        }
    }

    private class RadioButtonCell extends TableCell<Disposer.Record, Boolean> {

        final RadioButton cellRadioButton = new RadioButton();

        RadioButtonCell() {
            cellRadioButton.setToggleGroup(isPrimaryToggleGroup);

            //Action when the radio button is pressed
            cellRadioButton.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent t) {
                    // get Selected Item
                    int currentItemIndex = RadioButtonCell.this.getIndex();

                    // change attribute to selected?
                    attributes.get(currentItemIndex).setIsPrimary(true);
                    for (int i = 0; i < attributes.size(); i++) {
                        if (i != currentItemIndex) {
                            attributes.get(i).setIsPrimary(false);
                        }
                    }
                }
            });
        }

        //Display button if the row is not empty
        @Override
        protected void updateItem(Boolean t, boolean empty) {
            super.updateItem(t, empty);
            if (!empty) {
                cellRadioButton.setSelected(t);
                setGraphic(cellRadioButton);
            }
        }
    }
}
